#pragma once

#include <functional>
#include <vector>
#include <atomic>
#include <memory>
#include <mutex>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/eventfd.h>

#include "Channel.h"
#include "noncopyable.h"
#include "Timestamp.h"
#include "Poller.h"
#include "CurrentThread.h"

// 事件循环类主要包含两大模块，分别是Channel和Poller
class EventLoop : noncopyable
{
public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    // 开启事件循环
    void loop();
    // 退出事件循环
    void quit();

    Timestamp pollReturnTime() const { return pollReturnTime_; }

    // 在当前的loop执行回调cb
    void runInLoop(Functor cb);
    // 将cb放入队列中，唤醒loop所在的线程，执行cb回调
    void queueInLoop(Functor cb);

    // 用来唤醒loop所在的线程的
    void wakeup();

    // 以下的方法都是调用Poller的方法
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel* channel);

    // 判断EventLoop对象是否在自己的线程里面
    bool isInLoopThread() { return threadId_ == CurrentThread::tid(); }

private:
    void handleRead(); // wake up
    void doPendingFunctors(); // 执行回调

    using ChannelList = std::vector<Channel*>;

    std::atomic_bool looping_;  // 标识是否正在looping
    std::atomic_bool quit_; // 标识是否退出事件循环
    
    const pid_t threadId_; // 记录当前loop所在线程的id

    Timestamp pollReturnTime_; // Poller返回发生事件的时间点
    std::unique_ptr<Poller> poller_;

    // 当mainLoop获取一个新用户的channel，通过轮询算法选择一个
    //  subLoop，通过wakeupFd_唤醒subLoop处理channel
    int wakeupFd_;
    std::unique_ptr<Channel> wakeupChannel_;

    ChannelList activeChannels_; // 活跃的Channel

    std::atomic_bool callingPendingFunctors_; // 标识当前loop是否有需要执行的回调操作
    std::vector<Functor> pendingFunctors_; // 存储loop需要执行的所有的回调操作
    std::mutex mutex_; // 互斥锁，用来保护上面vector容器的线程安全操作
};